package com.laundry.service;

import com.laundry.dto.LoginRequest;
import com.laundry.dto.RegisterRequest;
import com.laundry.dto.UserResponse;
import com.laundry.entity.User;
import com.laundry.repository.UserRepository;
import com.laundry.util.JwtUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;

@Service
@RequiredArgsConstructor
public class AuthService {

    private final UserRepository userRepository;
    private final PasswordEncoder passwordEncoder;
    private final AuthenticationManager authenticationManager;
    private final JwtUtil jwtUtil;
    private final StringRedisTemplate redisTemplate;
    
    @Transactional
    public Map<String, Object> login(LoginRequest request) {
        // 认证用户
        Authentication authentication = authenticationManager.authenticate(
            new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword())
        );
        
        SecurityContextHolder.getContext().setAuthentication(authentication);
        
        // 获取用户信息 - 优先按用户名查找，避免重复数据问题
        User user = userRepository.findByUsername(request.getUsername()).orElse(null);
        if (user == null) {
            user = userRepository.findByEmail(request.getUsername()).orElse(null);
        }
        if (user == null) {
            user = userRepository.findByMobile(request.getUsername()).orElse(null);
        }
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }
        
        // 更新最后登录时间
        user.setLastLoginTime(LocalDateTime.now());
        userRepository.save(user);
        
        // 生成JWT token
        String token = jwtUtil.generateToken(user.getUsername());
        
        Map<String, Object> result = new HashMap<>();
        result.put("token", token);
        result.put("user", UserResponse.fromUser(user));
        
        return result;
    }
    
    @Transactional
    public UserResponse register(RegisterRequest request) {
        // 检查用户名是否已存在
        if (userRepository.existsByUsername(request.getUsername())) {
            throw new RuntimeException("用户名已存在");
        }
        
        // 检查邮箱是否已存在
        if (userRepository.existsByEmail(request.getEmail())) {
            throw new RuntimeException("邮箱已存在");
        }
        
        // 检查手机号是否已存在
        if (request.getMobile() != null && userRepository.existsByMobile(request.getMobile())) {
            throw new RuntimeException("手机号已存在");
        }
        
        // 创建新用户
        User user = new User();
        user.setUsername(request.getUsername());
        user.setEmail(request.getEmail());
        user.setPassword(passwordEncoder.encode(request.getPassword()));
        user.setMobile(request.getMobile());
        user.setStatus(User.UserStatus.ACTIVE);
        user.setRole(User.UserRole.USER);
        
        User savedUser = userRepository.save(user);
        
        return UserResponse.fromUser(savedUser);
    }
    
    public UserResponse getCurrentUser() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication == null || !authentication.isAuthenticated()) {
            throw new RuntimeException("用户未登录");
        }

        String username = authentication.getName();
        // 优先按用户名查找，避免重复数据问题
        User user = userRepository.findByUsername(username).orElse(null);
        if (user == null) {
            user = userRepository.findByEmail(username).orElse(null);
        }
        if (user == null) {
            user = userRepository.findByMobile(username).orElse(null);
        }
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }

        return UserResponse.fromUser(user);
    }

    public boolean isUsernameExists(String username) {
        return userRepository.existsByUsername(username);
    }

    /**
     * 发送短信验证码
     */
    public void sendSmsCode(String phone, String type) {
        // 检查发送频率限制（60秒内只能发送一次）
        String frequencyKey = "sms:frequency:" + phone;
        if (redisTemplate.hasKey(frequencyKey)) {
            throw new RuntimeException("发送过于频繁，请稍后再试");
        }

        // 生成6位随机验证码
        String code = String.format("%06d", new Random().nextInt(999999));

        // 存储验证码到Redis，5分钟过期
        String codeKey = "sms:code:" + phone + ":" + type;
        redisTemplate.opsForValue().set(codeKey, code, 5, TimeUnit.MINUTES);

        // 设置发送频率限制，60秒过期
        redisTemplate.opsForValue().set(frequencyKey, "1", 60, TimeUnit.SECONDS);

        // TODO: 这里应该调用真实的短信服务商API发送短信
        // 目前只是模拟发送，实际项目中需要集成阿里云、腾讯云等短信服务
        System.out.println("发送验证码到手机号: " + phone + ", 验证码: " + code + ", 类型: " + type);

        // 记录发送日志
        System.out.println("SMS sent to " + phone + " with code " + code + " for " + type);
    }

    /**
     * 验证短信验证码
     */
    public boolean verifySmsCode(String phone, String code, String type) {
        String codeKey = "sms:code:" + phone + ":" + type;
        String storedCode = redisTemplate.opsForValue().get(codeKey);

        if (storedCode == null) {
            return false; // 验证码不存在或已过期
        }

        if (storedCode.equals(code)) {
            // 验证成功，删除验证码
            redisTemplate.delete(codeKey);
            return true;
        }

        return false;
    }

    /**
     * 验证码登录
     */
    @Transactional
    public Map<String, Object> loginWithCode(String mobile, String code) {
        // 验证验证码
        if (!verifySmsCode(mobile, code, "login")) {
            throw new RuntimeException("验证码错误或已过期");
        }

        // 查找用户，如果不存在则自动创建
        User user = userRepository.findByMobile(mobile).orElse(null);
        if (user == null) {
            // 自动创建用户
            user = new User();
            user.setMobile(mobile);
            user.setUsername("user_" + mobile); // 自动生成用户名
            user.setPassword(passwordEncoder.encode("123456")); // 默认密码
            user.setStatus(User.UserStatus.ACTIVE);
            user.setRole(User.UserRole.USER);
            user = userRepository.save(user);
        }

        // 更新最后登录时间
        user.setLastLoginTime(LocalDateTime.now());
        userRepository.save(user);

        // 生成JWT token
        String token = jwtUtil.generateToken(user.getUsername());

        Map<String, Object> result = new HashMap<>();
        result.put("token", token);
        result.put("user", UserResponse.fromUser(user));

        return result;
    }
}
